\section{Previous work}

In their article \cite{Constanza:2008}, \cnh{} give a
simple example of this simple \texttt{defmethod} form:

\begin{verbatim}
(defmethod foo ((x integer) (y integer))
  (do-something x y))
\end{verbatim}

\noindent
and at the end of section 2.1, on page 3, they claim that the
expansion of that form is ``something like'' the follow form:

{\small\begin{verbatim}
(let ((gf (ensure-generic-function 'foo)))
  (multiple-value-bind
      (lambda-expression extra-initargs)
      (make-method-lambda
        gf
        (class-prototype
          (generic-function-method-class gf))
        '(lambda (x y) (do-something x y))
        lexical-environment-of-defmethod-form)
    (add-method
      gf
      (apply #'make-instance
             (generic-function-method-class gf)
             :qualifiers '()
             :lambda-list '(x y)
             :specializers (list (find-class 'integer)
                                 (find-class 'integer))
             :function (compile nil lambda-expression)
             extra-initargs))
\end{verbatim}}

\noindent
except that we have formatted the code to fit the page, and we have
added two missing closing parentheses at the end of the form.

This example is a slight variation on the code that is shown in
section 5.5.1 of the AMOP book.  However, in that section, it is not
claimed that this code is the result of expanding a \texttt{defmethod}
form.  Rather, it is given as ``an example of creating a generic
function and a method metaobject, and then adding the method to the
generic function''.

Indeed, this expansion is not possible, at least not in a compiling
implementation, which is the premise of both the paper by \cnh{} and
this one.  It has two fundamental problems:

\begin{enumerate}
\item The call to \mml{} must be made at macro-expansion time, whereas
  in their example, the call is present in the expansion, so it will
  be made at load time.
\item In their example, the resulting method lambda is compiled in the
  null lexical environment.  However, compiling in the null lexical
  environment would violate the semantics of the \commonlisp{}
  standard, which requires that the body of the \texttt{defmethod}
  form be compiled in the lexical environment in which it appears.
\end{enumerate}

In section 5.4.3 of the AMOP book, an example of an expansion is
shown, and figure 5.4 clearly mentions that \mml{} is called during
the macro-expansion phase.  Furthermore, in figure 5.3, which shows the
expansion of the \texttt{defmethod} macro, no call to \texttt{compile}
is made.  The result of calling \mml{}, i.e., the \emph{method lambda}
is simply present in the expanded code.

As \cnh{} point out, the \texttt{defmethod} macro does
not allow the programmer to specify a class for the method to be
created.  That class must be determined by the generic function to
which the method is ultimately going to be added.  Therefore, in the
case of a \texttt{defgeneric} form followed by a \texttt{defmethod}
form, the method class must be the one indicated in the
\texttt{defgeneric} form.

The conundrum, then, is that the file compiler does not create the
generic function as a result of compiling the \texttt{defgeneric}
form, so when a \texttt{defmethod} form with the same name is
encountered later in the same file, the method class can not be taken
from the generic function metaobject.  Otherwise, the normal way of
obtaining the method class would be to call the accessor
\texttt{generic\--function\--method\--class}, passing it the generic
function metaobject with the name indicated in the \texttt{defmethod}
form.  If there is no way for the file compiler to determine the
method class when the \texttt{defmethod} form is encountered, then
clearly the only choice is to call \mml{} with the class prototype of
the class named \texttt{standard-method} as the second argument.
However, the analysis by \cnh{} is that this behavior is a result of
the file compiler calling \texttt{ensure-generic-function} to obtain a
generic-function metaobject and then querying that object to obtain
the method class.  A simple experiment shows that this is not the case
in \sbcl{} for instance.

When the following code is compiled with the \sbcl{} file compiler:

\begin{verbatim}
(defclass hello (standard-method) ())

(defgeneric foo (x y)
  (:method-class hello))

(defmethod foo (x y)
  (+ x y))

(eval-when (:compile-toplevel)
  (print (fdefinition 'foo)))
\end{verbatim}

\noindent
the compilation fails when an attempt is made to find the definition
of \texttt{foo} in the last top-level form.  Thus, after the
\texttt{defmethod} form has been compiled, the generic-function
metaobject still does not exist in the compilation environment.

However, tracing \mml{} prior to compiling the code above in a fresh
compilation environment reveals that 
\mml{} is indeed called as a
result of compiling the \texttt{def\-method} form, and that the second
argument passed to the call is an instance of
\texttt{standard-method}.

This situation can lead to some problems in client code that are amply
described in the paper by \cnh{}.  The essence of the
problem is that, when a \texttt{defgeneric} form with a
non-standard \texttt{:method-class} option is followed by a
\texttt{defmethod} form in the same file, the file compiler may
generate an expansion of the \texttt{defmethod} form that creates an
instance of \texttt{standard-method} when the compiled file is
ultimately loaded, as opposed to an instance of the method class with
the name that was explicitly mentioned in the \texttt{defgeneric}
form.

Furthermore, this behavior is inconsistent with the behavior when the
source file is processed using \texttt{load}.  The reason is that,
contrary to the file compiler, \texttt{load} completely processes and
evaluates each top-level form in order.  As a result, when
\texttt{load} is used, the generic function metaobject \emph{is}
created as a result of evaluating the \texttt{defgeneric} form, so
that it \emph{does} exist when the \texttt{defmethod} form is
ultimately evaluated.  Clearly, such inconsistent behavior between
directly loading a source file and loading the result of applying the
file compiler to it first is highly undesirable.

Perhaps even worse, even when the file compiler is used consistently,
if the file is recompiled after having been loaded previously, the
existing generic-function metaobject is reinitialized to have the
correct method class, and the code works as when \texttt{load} is
used.

The ultimate conclusion by \cnh{} is that, in order for
the behavior of the file compiler to be consistent with that of
loading the source file directly, and indeed for that behavior to be
correct, the file compiler \emph{must} create the generic function
metaobject at compile time, so that it can be queried for the desired
method class when the \texttt{defmethod} form is encountered.  In the
next section, we propose an alternative solution to this conundrum.

To solve the perceived problems with \mml{}, \cnh{} first analyze what
desirable features this function has, and conclude that the following
two are essential:

\begin{enumerate}
\item It can add new lexical definitions inside method bodies.  This
  is the feature that is used to introduce definitions of
  \texttt{next-method-p} and \texttt{call\--next\--method}.
\item It can create lambda expressions for method functions with
  parameters in addition to the usual two, namely one for holding the
  arguments to the generic function and another for holding a list of
  next methods.
\end{enumerate}

With these essential features in mind, \cnh{} then propose an
alternative to \mml{} that does not have the perceived problem that
this function has.

Their proposed solution has two parts:

\begin{enumerate}
\item They use custom method-defining macros.  Such a macro would
  expand to a \texttt{defmethod} form, but this form can contain
  additional lexical definitions into the method body, introduced by
  the custom macro.
\item They propose that method functions always be able to take
  additional parameters in the form of \commonlisp{} keyword
  parameters.  Furthermore, the use of the lambda-list keyword
  \texttt{\&allow-other-keys} would make it easier to combine method
  functions that accept different additional arguments.
\end{enumerate}

While it is able to solve the problem of the inconsistent behavior
between \texttt{compile-file} and \texttt{load}, this solution has two
major disadvantages as pointed out by \cnh{}:

\begin{enumerate}
\item With this solution, method functions have a lambda list that
  includes keyword parameters.  Processing keyword arguments imposes a
  significant performance penalty on the invocation of method
  functions.
\item Existing \clos{} implementations that use a lambda list without
  any keyword parameter for method functions are incompatible with
  this solution.
\end{enumerate}

In the next section, we propose a solution that has neither of these
disadvantages.

%%  LocalWords:  metaobject defmethod defgeneric
